package kassiopeia.plugin.crawler.downloader;

import java.io.IOException;
import java.net.URL;
import kassiopeia.plugin.Context;
import kassiopeia.plugin.Event;
import kassiopeia.plugin.PluginException;
import kassiopeia.plugin.ProcessorPlugin;
import org.apache.log4j.Logger;

public class DownloaderPlugin extends ProcessorPlugin {

    private final Logger logger = Logger.getLogger(DownloaderPlugin.class);

    // Event headers
    public static final String URL_HEADER_NAME = "URL";
    public static final String MIME_TYPE_HEADER_NAME = "MIME_TYPE";

    // Outputs
    public static final String OUTPUT = "out";

    // Parameters
    public static final String MAX_CONTENT_LENGTH_PARAM = "maximum-content-length";
    public static final String DOWNLOAD_DELAY_PARAM = "download-delay";

    private DownloaderFactory downloaderFactory = new DownloaderFactoryImpl();
    private long maxContentLength;
    private long downloadDelay;

    // Constructor for testing purposes only
    public DownloaderPlugin(Context context, DownloaderFactory downloaderFactory, long maxContentLength) {
        super(context);
        this.downloaderFactory = downloaderFactory;
        this.maxContentLength = maxContentLength;
    }

    public DownloaderPlugin() {
        this.downloaderFactory = new DownloaderFactoryImpl();
    }

    @Override
    public void beforeTask() {
        maxContentLength = Long.parseLong(getContext().getParameter(MAX_CONTENT_LENGTH_PARAM));
        downloadDelay = Long.parseLong(getContext().getParameter(DOWNLOAD_DELAY_PARAM));
    }

    @Override
    public final void process(Event event) {
        URL url = getNotNullableEventBody(event, URL.class);
        String urlString = url.toExternalForm();
        Downloader downloader = null;
        try {
            downloader = downloaderFactory.getDownloader(url, maxContentLength);

            Event outgoingEvent = new Event();
            outgoingEvent.setBody(downloader.getContent());

            String mimeType = downloader.getMimeType();
            outgoingEvent.setHeader(MIME_TYPE_HEADER_NAME, mimeType);
            outgoingEvent.setHeader(URL_HEADER_NAME, url);

            logger.info("Downloaded resource (" + urlString + ", MIME: " + mimeType +")");

            delay();

            getContext().sendLocally(outgoingEvent, OUTPUT);
        } catch (IOException exception) {
            throw new PluginException("Error while downloading resource: " + urlString, exception);
        }
    }

    private void delay() {
        try {
            if(downloadDelay > 0) {
                Thread.sleep(downloadDelay);
            }
        } catch(InterruptedException exception) {
            logger.warn("Delaying download interrupted");
        }
    }

    public DownloaderFactory getDownloaderFactory() {
        return downloaderFactory;
    }

    public void setDownloaderFactory(DownloaderFactory downloaderFactory) {
        this.downloaderFactory = downloaderFactory;
    }
}
